﻿// Autore: Emanuele Poggi

using System;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
using NUnit.Framework;
using RecipesManager.Data;
using TechTalk.SpecFlow;
using White.Core.Factory;
using White.Core.UIItems.Finders;
using White.Core.UIItems.WindowItems;
using Button = White.Core.UIItems.Button;

namespace RecipesManager.Specs.Evento
{
    [Binding]
    [Scope(Feature = "AggiungiEvento")]
    public class AggiungiEvento_Steps : EventiBdd
    {
        Window _dialog;
        Button _confirm;
        Button _cancel;
        Button _accept;

        void GetAcceptDialogUi()
        {
            _dialog = MainWindow.ModalWindows()[0];
            _accept = MainWindow.Get<Button>("2");
        }

        void GetConfirmDialogUi()
        {
            _dialog = MainWindow.ModalWindows()[0];
            _confirm = MainWindow.Get<Button>("6");
            _cancel = MainWindow.Get<Button>("7");
        }

        [Then(Regex = @"appare un messaggio")]
        public void AppareMessaggio()
        {
            Assert.That(MainWindow.ModalWindows().Count() == 1);
        }

        [When(Regex = "confermo")]
        public void QuandoConfermo()
        {
            this.GetConfirmDialogUi();
            _confirm.Click();
            Assert.That(!MainWindow.ModalWindows().Any());
        }

        [When(Regex = "rifiuto")]
        public void QuandoRifiuto()
        {
            this.GetConfirmDialogUi();
            _cancel.Click();
            Assert.That(!MainWindow.ModalWindows().Any());
        }

        [When(Regex = "accetto")]
        public void QuandoAccetto()
        {
            this.GetAcceptDialogUi();
            _accept.Click();
            Assert.That(!MainWindow.ModalWindows().Any());
        }

        [BeforeScenario]
        public new void SetUpScenario()
        {
            base.SetUpScenario();
        }

        [AfterScenario]
        public new void TearDownScenario()
        {
            base.TearDownScenario();
        }

        [AfterStep]
        [BeforeStep]
        public void MiniStop()
        {
            MainWindow.WaitWhileBusy();
            MainWindow.ReloadIfCached();
            MainWindow.ReInitialize(InitializeOption.NoCache);
        }

        [Given(Regex = "l'ospite \"([a-zA-Z ]+)\" esiste")]
        public void DatoEsisteOspite(string ospite)
        {
            Manager.Guests.Add(ospite);
        }

        [Given(Regex = "l'ospite \"([a-zA-Z ]+)\" è \"([a-zA-Z ]+)\" per \"([a-zA-Z ]+)\"")]
        public void DatoOspiteOspite(string soggetto, string rapporto, string ospite)
        {
            var guestRating = GuestRating.VeryGood;
            switch ( rapporto )
            {
                case "molto sgradito" : guestRating = GuestRating.VeryBad;
                    break;

                case "sgradito": guestRating = GuestRating.Bad;
                    break;

                case "molto gradito": guestRating = GuestRating.VeryGood;
                    break;

                case "gradito": guestRating = GuestRating.Good;
                    break;

                case "indifferente": guestRating = GuestRating.Neuter;
                    break;

                case "indispensabile":
                    Manager.Guests[ospite].GuestRelationships.Add(soggetto);
                    return;

                default :  Assert.Fail("Guest Rating");
                    break;
            }
            Manager.Guests[ospite].GuestRatings.Add(soggetto,guestRating);
        }

        [Given(Regex = "l'ospite \"([a-zA-Z ]+)\" è intollerante a \"([a-zA-Z ]+)\" \"([a-zA-Z ]+)\"")]
        public void DatoOspiteIntollerante(string ospite, string tipo, string nome)
        {
            switch (tipo)
            {
                case "categoria": Manager.Guests[ospite].CategoryIntolerances.Add(nome);
                    break;

                case "ingrediente": Manager.Guests[ospite].IngredientIntolerances.Add(nome);
                    break;

                default: Assert.Fail("Intolerance type");
                    break;
            }          
        }

        [Given(Regex = "\"([a-zA-Z ]+)\" \"([a-zA-Z ]+)\" \"([a-zA-Z ]+)\" a \"([a-zA-Z ]+)\"")]
        public void DatoPreferenzaOspite(string tipo, string soggetto , string rate, string ospite)
        {
            var guestRating = FoodRating.VeryGood;
            switch (rate)
            {
                case "molto sgradito": guestRating = FoodRating.VeryBad;
                    break;

                case "sgradito": guestRating = FoodRating.Bad;
                    break;

                case "molto gradito": guestRating = FoodRating.VeryGood;
                    break;

                case "gradito": guestRating = FoodRating.Good;
                    break;

                case "indifferente": guestRating = FoodRating.Neuter;
                    break;

                default: Assert.Fail("Guest Rating");
                    break;
            }

            switch( tipo )
            {
                case "categoria":
                    Manager.Guests[ospite].CategoryRatings.Add(soggetto,guestRating);
                    break;

                case "ingrediente": 
                    Manager.Guests[ospite].IngredientRatings.Add(soggetto,guestRating);
                    break;

                case "ricetta":
                    Manager.Guests[ospite].RecipeRatings.Add(soggetto,guestRating);
                    break;

                default: Assert.Fail("Intolerance type");
                    break;
            }         
        }

        [Given(Regex = "la ricetta \"([a-zA-Z ]+)\" esiste")]
        public void DatoEsisteRicetta(string ricetta)
        {
            Manager.Recipes.Add(ricetta);
        }

        [Given(Regex = "la categoria \"([a-zA-Z ]+)\" esiste")]
        public void DatoEsisteCategoria(string categoria)
        {
            Manager.Categories.Add(categoria);
        }

        [Given(Regex = "l'ingrediente \"([a-zA-Z ]+)\" appartiene alla categoria \"([a-zA-Z ]+)\"")]
        public void DatoEsisteRicettaCategoria( string ingrediente, string categoria )
        {
            Manager.Ingredients[ingrediente].Categories.Add(categoria);
        }

        [Given(Regex = "la ricetta \"([a-zA-Z ]+)\" esiste con \"([0-9]+)\" \"([a-zA-Z ]+)\" di \"([a-zA-Z ]+)\"")]
        public void DatoEsisteRicettaConIngrediente(string ricetta,string quantità , string unità ,string ingrediente)
        {
            // usiamo solo peso
            if( Manager.Ingredients.Any(i => i.Name.Equals(ingrediente)) == false)
                Manager.Ingredients.Add(ingrediente, MeasureType.Weight);

            var r = Manager.Recipes.Add(ricetta,"",MeasureFamily.None,1,30,1);
            r.Ingredients.Add(ingrediente, unità, double.Parse(quantità));
        }

        [Given(Regex = "l'ospite \"([a-zA-Z ]+)\" non esiste")]
        public void DatoNonEsisteOspite(string ospite)
        {
            Assert.That(!Manager.Guests.Contains(ospite));
        }

        [Given(Regex = "l'evento \"([a-zA-Z ]+)\" esiste")]
        public void DatoEsisteEvento(string evento)
        {
            Manager.Events.Add(evento);
        }

        [Given(Regex = "l'evento \"([a-zA-Z ]+)\" non esiste")]
        public void DatoNonEsisteEvento(string evento)
        {
            var events = Manager.Events.AsQueryable();
            var ev = events.Where(e => e.Name == evento);

            Assert.That(!ev.Any());
        }

        [When(Regex ="aggiungo ricetta a lista della spesa")]
        public void QuandoAggiungoRicettaAListaDellaSpesa()
        {
            Cursor.Position = new Point((int)AddRecipe.Location.X - 150, (int)AddRecipe.Location.Y + 58);
            //Thread.Sleep(5000);
           
            MainWindow.Mouse.Click();
            Assert.That(AddRecipeToList.Enabled);
            AddRecipeToList.Click();
        }

        [When(Regex = "aggiungo menu a lista della spesa")]
        public void QuandoAggiungoMenuAListaDellaSpesa()
        {
            Assert.That(AddMenuToShoppingList.Enabled);
            AddMenuToShoppingList.Click();
        }

        [Given(Regex = "la lista della spesa è vuota")]
        public void DataListaDellaSpesaVuota()
        {
            Assert.That(!Manager.ShoppingList.Any());
        }

        [Then(Regex = "la lista della spesa non è vuota")]
        public void AlloraListaDellaSpesaNonVuota()
        {
            Manager.ClearCache();
            Assert.That( Manager.ShoppingList.Any() );
        }

        [Given(Regex = "ho inserito i valori")]
        public void DatoInseritoValori(Table table)
        {
            NavigateToEvents();
            GetEventUi();
            NewEvent.Click();

            GetSingleEventUi();

            foreach (var tableRow in table.Rows)
            {
                if (tableRow["Attributi"].Equals("Nome"))
                {
                    EventName.SetValue(tableRow["Valori"]);
                }
                else if (tableRow["Attributi"].Equals("Data"))
                {                 
                   
                    EventCalendar.Click();

                    Cursor.Position = new Point((int) EventCalendar.Location.X - 495,
                                                (int) EventCalendar.Location.Y + 45);
                    MainWindow.Mouse.Click();

                    Cursor.Position = new Point((int) EventCalendar.Location.X - 452,
                                                (int) EventCalendar.Location.Y + 82);
                    MainWindow.Mouse.Click();

                    Cursor.Position = new Point((int) EventCalendar.Location.X - 338,
                                                (int) EventCalendar.Location.Y + 200);
                    MainWindow.Mouse.Click();

                    Cursor.Position = new Point((int)EventCalendar.Location.X - 365,
                                                (int)EventCalendar.Location.Y + 230);
                    MainWindow.Mouse.Click();
                    MainWindow.Mouse.Click();
                    MainWindow.Mouse.Click();
                    MainWindow.Mouse.Click();

                    Cursor.Position = new Point((int) EventCalendar.Location.X - 450,
                                                (int) EventCalendar.Location.Y + 220);
                    MainWindow.Mouse.Click();
                    MainWindow.Mouse.Click();
                }

                else if (tableRow["Attributi"].Equals("Nota"))
                {
                    Note.Click();
                    Cursor.Position = new Point((int) Note.Location.X + 20, (int) Note.Location.Y + 30);
                    MainWindow.Mouse.Click();
                    MainWindow.Enter(tableRow["Valori"]);
                }

                else if (tableRow["Attributi"].Equals("Invitato"))
                {
                    EventsGuests.Enter(tableRow["Valori"]);
                    AddEventGuest.Click();                  
                }

                else if (tableRow["Attributi"].Equals("Ricetta"))
                {
                    var ricetta = tableRow["Valori"];
                    Menu.Enter(ricetta);
                    AddRecipe.Click();
                }

                else if (tableRow["Attributi"].Equals("Porzioni"))
                {
                    var num = int.Parse( tableRow["Valori"] );
                    Cursor.Position = new Point((int)AddRecipe.Location.X - 35, (int)AddRecipe.Location.Y + 55);                 
                    //Thread.Sleep(5000);
                    for (var i = 1; i < num; i++ )
                        MainWindow.Mouse.Click();
                }

                else
                {
                    Assert.Fail("Table");
                }
            }
        }

        [When(Regex = "salvo")]
        public void QuandoSalvo()
        {
            Assert.That(Save.Enabled);
            Save.Click();
        }

        [When(Regex = "chiudo l'evento")]
        public void QuandoChiudoEvento()
        {
            Assert.That(CloseEvent.Enabled);
            CloseEvent.Click();
        }

        [Then(Regex = "l'operazione ha successo")]
        public void AlloraSuccesso()
        {
            Assert.That(!MainWindow.ModalWindows().Any());
        }

        [Then(Regex = "l'operazione non ha successo")]
        public void AlloraInsuccesso()
        {
            Assert.That(MainWindow.ModalWindows().Count == 1);
        }

        [Then(Regex = "esiste l'evento \"([a-zA-Z ]+)\"")]
        public void AlloraEsisteEvento(string evento)
        {
            var events = Manager.Events.AsQueryable();
            var ev = events.Where(e => e.Name == evento);

            Assert.That(ev.Any());
        }

        [Then(Regex = "esiste l'evento con i valori")]
        public void AlloraEsisteEventoConData(Table table)
        {
            var events = Manager.Events.AsQueryable();

            foreach (var tableRow in table.Rows)
            {
                if (tableRow["Attributi"].Equals("Nome"))
                {
                    var evento = tableRow["Valori"];
                    events = events.Where(e => e.Name.Equals(evento) );
                }
                else if (tableRow["Attributi"].Equals("Data"))
                {
                    var data = DateTime.ParseExact(tableRow["Valori"], "MM/dd/yyyy",
                                                        CultureInfo.InvariantCulture, DateTimeStyles.None);
                    events = events.Where( e =>  e.Date.Equals(data) );
                }

                else if (tableRow["Attributi"].Equals("Invitato"))
                {
                    var guest = tableRow["Valori"];
                    events = events.Where(e => e.Guests.Any(g => g.Name.Equals(guest)));
                }

                else if (tableRow["Attributi"].Equals("Ricetta"))
                {
                    var ricetta = tableRow["Valori"];
                    events = events.Where(e => e.Recipes.Any(r => r.Name.Equals(ricetta)));
                }

                else if (tableRow["Attributi"].Equals("Porzioni"))
                {
                    var num = int.Parse(tableRow["Valori"]);

                    events = events.Where( e => e.Recipes.Any( r => r.Servings == num ) );
                }

                else
                {
                    Assert.Fail("Table");
                }
            }

            Assert.That(events.Any());
        }


        [Then(Regex = "non esiste l'evento \"([a-zA-Z ]+)\"")]
        public void AlloraNonEsisteEvento(string evento)
        {
            var events = Manager.Events.AsQueryable();
            var ev = events.Where(e => e.Name == evento);

            Assert.That(!ev.Any());
        }

        [Then(Regex = "esistono \"([0-9]+)\" eventi \"([a-zA-Z ]+)\"")]
        public void AlloraNonEsisteEvento( string num , string evento )
        {
            var events = Manager.Events.AsQueryable();
            var ev = events.Where(e => e.Name == evento);
            var n = int.Parse(num);
            Assert.That(ev.Count()==n);
        }

        [Then(Regex = "l'evento \"([a-zA-Z ]+)\" è chiuso")]
        public void AlloraEventoChiuso(string evento)
        {
            var events = Manager.Events.AsQueryable();
            var ev = events.Where(e => e.Name == evento && e.HasEnded);

            Assert.That(ev.Any());
        }

        [Then(Regex = "ho un errore")]
        public void AlloraErrore()
        {
            Console.WriteLine ( Conflicts.Rows.Count );
            Console.WriteLine ( Conflicts.Rows[0].Cells.Count);
            var element = Conflicts.Rows[0].GetElement(SearchCriteria.ByText("Errore"));
            if (element == null) 
                Assert.Fail();
        }

        [Then(Regex = "ho un avviso")]
        public void AlloraAvviso()
        {
            Console.WriteLine(Conflicts.Rows.Count);
            Console.WriteLine(Conflicts.Rows[0].Cells.Count);
            var element = Conflicts.Rows[0].GetElement(SearchCriteria.ByText("Avviso"));
            if (element == null)
                Assert.Fail();
        }
    }
}
